<template>
  <div class="tetris-game">
    <h1>俄罗斯方块</h1>
    <div class="game-container">
      <div class="game-board">
        <div 
          v-for="(row, y) in board" 
          :key="y" 
          class="board-row"
        >
          <div
            v-for="(cell, x) in row"
            :key="x"
            class="board-cell"
            :class="getCellClass(cell, x, y)"
          ></div>
        </div>
      </div>
      <div class="game-info">
        <div class="next-piece">
          <h3>下一个:</h3>
          <div class="next-piece-board">
            <div 
              v-for="(row, y) in nextPieceDisplay" 
              :key="y"
              class="next-piece-row"
            >
              <div
                v-for="(cell, x) in row"
                :key="x"
                class="next-piece-cell"
                :class="getNextPieceCellClass(cell)"
              ></div>
            </div>
          </div>
        </div>
        <div class="score">
          <p>分数: {{ score }}</p>
          <p>行数: {{ lines }}</p>
          <p>等级: {{ level }}</p>
        </div>
        <div class="controls">
          <button @click="startGame" v-if="!gameStarted || gameOver">开始游戏</button>
          <button @click="pauseGame" v-else>{{ isPaused ? '继续' : '暂停' }}</button>
        </div>
      </div>
    </div>
    <div class="instructions">
      <p>使用方向键 ← → 移动, ↑ 旋转, ↓ 加速下降, 空格 瞬间下落</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'

// 定义方块形状
const SHAPES = [
  // I
  [
    [0, 0, 0, 0],
    [1, 1, 1, 1],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
  ],
  // J
  [
    [1, 0, 0],
    [1, 1, 1],
    [0, 0, 0]
  ],
  // L
  [
    [0, 0, 1],
    [1, 1, 1],
    [0, 0, 0]
  ],
  // O
  [
    [1, 1],
    [1, 1]
  ],
  // S
  [
    [0, 1, 1],
    [1, 1, 0],
    [0, 0, 0]
  ],
  // T
  [
    [0, 1, 0],
    [1, 1, 1],
    [0, 0, 0]
  ],
  // Z
  [
    [1, 1, 0],
    [0, 1, 1],
    [0, 0, 0]
  ]
]

// 方块颜色
const COLORS = [
  'cyan',
  'blue',
  'orange',
  'yellow',
  'green',
  'purple',
  'red'
]

// 游戏状态
const board = ref<number[][]>([])
const currentPiece = ref<{ shape: number[][]; x: number; y: number; type: number } | null>(null)
const nextPiece = ref<{ shape: number[][]; type: number } | null>(null)
const score = ref(0)
const lines = ref(0)
const level = ref(1)
const isPaused = ref(false)
const gameOver = ref(false)
const gameStarted = ref(false)

// 游戏配置
const BOARD_WIDTH = 10
const BOARD_HEIGHT = 20
const INITIAL_SPEED = 1000 // 毫秒

// 游戏定时器
let gameTimer: number | null = null

// 初始化游戏板
const initBoard = () => {
  board.value = Array(BOARD_HEIGHT).fill(null).map(() => 
    Array(BOARD_WIDTH).fill(0)
  )
}

// 初始化游戏
const initGame = () => {
  initBoard()
  score.value = 0
  lines.value = 0
  level.value = 1
  isPaused.value = false
  gameOver.value = false
  gameStarted.value = true
  
  // 生成第一个和下一个方块
  generateNewPiece()
  generateNextPiece()
  
  // 开始游戏循环
  startGameLoop()
}

// 生成新方块
const generateNewPiece = () => {
  if (nextPiece.value) {
    // 使用下一个方块作为当前方块
    currentPiece.value = {
      shape: nextPiece.value.shape,
      x: Math.floor(BOARD_WIDTH / 2) - Math.floor(nextPiece.value.shape[0].length / 2),
      y: 0,
      type: nextPiece.value.type
    }
    
    // 生成新的下一个方块
    generateNextPiece()
  } else {
    // 如果没有下一个方块，则随机生成
    const type = Math.floor(Math.random() * SHAPES.length)
    const shape = SHAPES[type]
    currentPiece.value = {
      shape,
      x: Math.floor(BOARD_WIDTH / 2) - Math.floor(shape[0].length / 2),
      y: 0,
      type
    }
    
    // 生成下一个方块
    generateNextPiece()
  }
  
  // 检查游戏是否结束
  if (currentPiece.value && isCollision(currentPiece.value.x, currentPiece.value.y, currentPiece.value.shape)) {
    gameOver.value = true
    if (gameTimer) {
      clearInterval(gameTimer)
      gameTimer = null
    }
  }
}

// 生成下一个方块
const generateNextPiece = () => {
  const type = Math.floor(Math.random() * SHAPES.length)
  nextPiece.value = {
    shape: SHAPES[type],
    type
  }
}

// 获取下一个方块显示用的5x5矩阵
const nextPieceDisplay = computed(() => {
  if (!nextPiece.value) return Array(5).fill(null).map(() => Array(5).fill(0))
  
  const display = Array(5).fill(null).map(() => Array(5).fill(0))
  const shape = nextPiece.value.shape
  const offsetY = Math.floor((5 - shape.length) / 2)
  const offsetX = Math.floor((5 - shape[0].length) / 2)
  
  for (let y = 0; y < shape.length; y++) {
    for (let x = 0; x < shape[y].length; x++) {
      if (shape[y][x]) {
        display[offsetY + y][offsetX + x] = nextPiece.value.type + 1
      }
    }
  }
  
  return display
})

// 检查是否碰撞
const isCollision = (x: number, y: number, shape: number[][]) => {
  for (let i = 0; i < shape.length; i++) {
    for (let j = 0; j < shape[i].length; j++) {
      if (shape[i][j]) {
        const newX = x + j
        const newY = y + i
        
        if (
          newX < 0 || 
          newX >= BOARD_WIDTH || 
          newY >= BOARD_HEIGHT ||
          (newY >= 0 && board.value[newY][newX])
        ) {
          return true
        }
      }
    }
  }
  return false
}

// 旋转方块
const rotatePiece = (shape: number[][]) => {
  const N = shape.length
  const rotated = Array(N).fill(null).map(() => Array(N).fill(0))
  
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      rotated[j][N - 1 - i] = shape[i][j]
    }
  }
  
  return rotated
}

// 合并方块到游戏板
const mergePieceToBoard = () => {
  if (!currentPiece.value) return
  
  const { shape, x, y, type } = currentPiece.value
  
  for (let i = 0; i < shape.length; i++) {
    for (let j = 0; j < shape[i].length; j++) {
      if (shape[i][j]) {
        const boardY = y + i
        const boardX = x + j
        if (boardY >= 0 && boardY < BOARD_HEIGHT && boardX >= 0 && boardX < BOARD_WIDTH) {
          board.value[boardY][boardX] = type + 1
        }
      }
    }
  }
}

// 清除完整行
const clearLines = () => {
  let linesCleared = 0
  
  for (let y = BOARD_HEIGHT - 1; y >= 0; y--) {
    if (board.value[y].every(cell => cell !== 0)) {
      // 移除这一行
      board.value.splice(y, 1)
      // 在顶部添加一个新行
      board.value.unshift(Array(BOARD_WIDTH).fill(0))
      linesCleared++
      y++ // 重新检查当前行
    }
  }
  
  if (linesCleared > 0) {
    // 更新分数
    const linePoints = [40, 100, 300, 1200] // 1, 2, 3, 4行的分数
    score.value += linePoints[linesCleared - 1] * level.value
    lines.value += linesCleared
    
    // 每清除10行升一级
    level.value = Math.floor(lines.value / 10) + 1
  }
}

// 移动方块
const movePiece = (dx: number, dy: number) => {
  if (!currentPiece.value || isPaused.value || gameOver.value) return
  
  const { x, y, shape } = currentPiece.value
  const newX = x + dx
  const newY = y + dy
  
  if (!isCollision(newX, newY, shape)) {
    currentPiece.value.x = newX
    currentPiece.value.y = newY
    return true
  }
  
  // 如果向下移动发生碰撞，则合并方块
  if (dy > 0) {
    mergePieceToBoard()
    clearLines()
    generateNewPiece()
  }
  
  return false
}

// 旋转当前方块
const rotateCurrentPiece = () => {
  if (!currentPiece.value || isPaused.value || gameOver.value) return
  
  const { shape, x, y } = currentPiece.value
  const rotated = rotatePiece(shape)
  
  if (!isCollision(x, y, rotated)) {
    currentPiece.value.shape = rotated
  }
}

// 瞬间下落
const hardDrop = () => {
  if (!currentPiece.value || isPaused.value || gameOver.value) return
  
  while (movePiece(0, 1)) {
    // 持续下落直到碰撞
  }
}

// 游戏循环
const gameLoop = () => {
  if (isPaused.value || gameOver.value) return
  movePiece(0, 1)
}

// 开始游戏循环
const startGameLoop = () => {
  if (gameTimer) {
    clearInterval(gameTimer)
  }
  gameTimer = window.setInterval(gameLoop, INITIAL_SPEED / level.value)
}

// 开始游戏
const startGame = () => {
  if (gameTimer) {
    clearInterval(gameTimer)
  }
  initGame()
}

// 暂停游戏
const pauseGame = () => {
  isPaused.value = !isPaused.value
  if (!isPaused.value && gameStarted.value) {
    startGameLoop()
  } else if (gameTimer) {
    clearInterval(gameTimer)
    gameTimer = null
  }
}

// 获取单元格类名
const getCellClass = (cell: number, x: number, y: number) => {
  const classes = []
  
  if (cell) {
    classes.push(`cell-${COLORS[cell - 1]}`)
  }
  
  // 检查是否是当前活动方块的一部分
  if (currentPiece.value) {
    const { shape, x: pieceX, y: pieceY, type } = currentPiece.value
    const offsetX = x - pieceX
    const offsetY = y - pieceY
    
    if (
      offsetY >= 0 && 
      offsetY < shape.length && 
      offsetX >= 0 && 
      offsetX < shape[0].length && 
      shape[offsetY][offsetX]
    ) {
      classes.push(`cell-${COLORS[type]}`, 'active')
    }
  }
  
  return classes
}

// 获取下一个方块单元格类名
const getNextPieceCellClass = (cell: number) => {
  return cell ? `cell-${COLORS[cell - 1]}` : ''
}

// 键盘控制
const handleKeyDown = (e: KeyboardEvent) => {
  if (!gameStarted.value || gameOver.value) return
  
  switch (e.key) {
    case 'ArrowLeft':
      movePiece(-1, 0)
      break
    case 'ArrowRight':
      movePiece(1, 0)
      break
    case 'ArrowDown':
      movePiece(0, 1)
      break
    case 'ArrowUp':
      rotateCurrentPiece()
      break
    case ' ':
      hardDrop()
      break
    case 'p':
      pauseGame()
      break
  }
}

// 组件挂载时添加事件监听
onMounted(() => {
  window.addEventListener('keydown', handleKeyDown)
})

// 组件卸载时移除事件监听
onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
  if (gameTimer) {
    clearInterval(gameTimer)
  }
})
</script>

<style scoped>
.tetris-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.game-container {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}

.game-board {
  border: 2px solid #333;
  background-color: #111;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}

.board-row {
  display: flex;
}

.board-cell {
  width: 20px;
  height: 20px;
  border: 1px solid #333;
  box-sizing: border-box;
}

.cell-cyan { background-color: cyan; }
.cell-blue { background-color: blue; }
.cell-orange { background-color: orange; }
.cell-yellow { background-color: yellow; }
.cell-green { background-color: green; }
.cell-purple { background-color: purple; }
.cell-red { background-color: red; }

.board-cell.active {
  border: 1px solid white;
  box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.5);
}

.game-info {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.next-piece h3 {
  margin-top: 0;
  text-align: center;
}

.next-piece-board {
  border: 2px solid #333;
  background-color: #111;
  padding: 10px;
}

.next-piece-row {
  display: flex;
}

.next-piece-cell {
  width: 20px;
  height: 20px;
}

.score {
  background-color: #f0f0f0;
  padding: 15px;
  border-radius: 5px;
}

.score p {
  margin: 5px 0;
  font-weight: bold;
}

.controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

button {
  padding: 10px 15px;
  font-size: 16px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #45a049;
}

.instructions {
  background-color: #f0f0f0;
  padding: 10px;
  border-radius: 5px;
  text-align: center;
  max-width: 500px;
}

.instructions p {
  margin: 0;
}
</style>